<?php
/**
 * Created by PhpStorm.
 * User: HP_USER
 * Date: 2018/9/13
 * Time: 17:30
 */

include_once ('./block.php');
include_once ('./CuteDB.php');

/**
 * 我们使用区块的Hash值作为键，将区块序列化后作为值来存储。而使用“lasthash”作为键来保存最后一个区块的Hash值，
 * 这样的话就可以通过最后一个区块的Hash值来不断回溯整个区块链的所有区块。
 */
class Blockchain
{
    public $blocks = [];//块链对象来保存整条区块链
    const dbFile='blockchain';//数据库文件
    const lastHashField ='lasthash';//获取最后一个哈希文件
    private $_db=null;//数据库对象
    private $_lastHash=null;

    public function __construct()
    {
        $this->_db =new CuteDB();
        if(!$this->_db->open(Blockchain::dbFile)){
            exit("Failed to create/open blockchian database");
        }
        $this->_lastHash =$this->_db->get(Blockchain::lastHashField);//获取最后一个hash值
        if (!$this->_lastHash){//不存区块链
            $block = new Block('','Genesis Block');
            $hash = $block->getBlockHash();//获取hash值
            $this->_db->set($hash, serialize($block));//设置键值
            $this->_db->set(Blockchain::lastHashField, $hash);//设置最后一个键的键值
            $this->_lastHash = $hash;//最后一次的hash值
        }
//        $this->blocks[]=new Block('','Genesis Block');
    }

    public function addBlock($data)
    {
//        $prevBlock=$this->blocks[count($this->blocks)-1];//获取最末尾的区块链对象
//        $this->blocks[]=new Block($prevBlock->getBlockHash(),$data);//存入新添加的区块链对象
        $newBlock = new Block($this->_lastHash, $data);
        $hash = $newBlock->getBlockHash();
        $this->_db->set($hash, serialize($newBlock));
        $this->_db->set(Blockchain::lastHashField, $hash);
        $this->_lastHash = $hash;
    }

    public function printBlockchain()
    {
        $lastHash = $this->_lastHash;

        while (true) {
            $block = $this->_db->get($lastHash);
            if (!$block) {
                break;
            }

            $block = unserialize($block);
            printf("PrevHash: %s<br>", $block->prevHash);
            printf("Hash: %s<br>", $block->hash);
            printf("Data: %s<br>", $block->data);
            printf("PoW: %s<br>", $block->validate() ? 'true' : 'false');
            printf("Nonce: %s<br>", $block->nonce);
            printf('<br>');

            $lastHash = $block->prevHash;
        }
    }
}